<?php

class Path implements Iterator {

    /**
     * @var int
     */
    private $index = 0;

    /**
     * @var array
     */
    private $data = array();

    /**
     * @var Path
     */
    protected static $instance;

    public static function getInstance() {
        if (!self::$instance) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    protected function __construct() {
        $url = parse_url($_SERVER['REQUEST_URI']);

        $this->data = isset($url['path'])
            ? explode('/', urldecode($url['path']))
            : array();

        $this->rewind();
    }

    /**
     * (PHP 5 &gt;= 5.0.0)<br/>
     * Return the current element
     * @link http://php.net/manual/en/iterator.current.php
     * @return mixed Can return any type.
     */
    public function current() {
        return isset($this->data[$this->index]) ? $this->data[$this->index] : null;
    }

    public function setCurrent($value) {
        $this->data[$this->index] = $value;
        return $this;
    }

    /**
     * (PHP 5 &gt;= 5.0.0)<br/>
     * Move forward to next element
     * @link http://php.net/manual/en/iterator.next.php
     * @return void Any returned value is ignored.
     */
    public function next() {
        $this->index++;
    }

    /**
     * (PHP 5 &gt;= 5.0.0)<br/>
     * Return the key of the current element
     * @link http://php.net/manual/en/iterator.key.php
     * @return mixed scalar on success, or null on failure.
     */
    public function key() {
        return $this->index;
    }

    /**
     * (PHP 5 &gt;= 5.0.0)<br/>
     * Checks if current position is valid
     * @link http://php.net/manual/en/iterator.valid.php
     * @return boolean The return value will be casted to boolean and then evaluated.
     * Returns true on success or false on failure.
     */
    public function valid() {
        return isset($this->data[$this->index]);
    }

    /**
     * (PHP 5 &gt;= 5.0.0)<br/>
     * Rewind the Iterator to the first element
     * @link http://php.net/manual/en/iterator.rewind.php
     * @return void Any returned value is ignored.
     */
    public function rewind() {
        $this->index = 0;
    }

    public function append(array $a) {
        $this->data = array_merge($this->data, $a);
    }

    public function tail() {
        return array_slice($this->data, $this->index);
    }

    public function join($glue) {
        return implode($glue, $this->data);
    }
}